//11.ts里面的类
// People2 父类 或 超类
class People2{
    private firstName:string=""; //只能自己类内部访问
    protected lastName:string=""; //子类或自己都可以访问 对象不能访问
    noses:string="隆鼻"; //没有访问修饰符 默认就是public
    constructor(protected eye:string){//构造函数可以写访问修饰符
        //这种访问修饰符的写法和 上面直接声明的一样
        this.eye=eye;
    }
}
// Student是子类 或 派生类
// 访问修饰符
class Student extends People2{
    //private 修饰的是私有属性，属性不能被对象和子类读取
    private age:number=18;
    //public 修饰的是共有属性,属性可以被子类和对象读取修改
    public username:string="laoxie";
    //protected 受保护的属性，它和 private 类似，区别是它在子类中也是允许被访问的,在对象不能访问
    protected money:number=10.0;
    //只读属性
    readonly gender:string="男";
    //静态属性 通过类调用
    static hair:string="长发";
    //构造函数
    constructor(){
        super('单眼皮');//执行父类的构造函数
    }
    public run(speed:number) {
        //在类的内部可以获取
        this.age;//正确
        this.money;//正确
        // this.firstName;// Error 私有属性不能在子类和对象被访问
        this.lastName;//正确 protected 属性子类中也是允许被访问的
        this.eye;//正确
    }
}
let jerry=new Student();
    // jerry.age;//私有 Error
    jerry.username;
    // jerry.money;// protected受保护的属性 只能类的内部或子类调用
    jerry.gender;
    // jerry.gender="女";//只读属性 Error
    // jerry.hair; //hair是静态 只能通过类名访问 Error
    Student.hair="短发";//正确
    // jerry.eye; //在构造函数里面定义的访问修饰符
    jerry.noses;//
//11.1 用接口验证对象.
interface Man2{
    username:string,
    noses:string,
    run:(speed:number)=>void
}
//用接口来验证对象. 只能是公共属性.
let huluwa:Man2=new Student();
//11.2 抽象类 abstract  有抽象方法的类就是抽象类.
// 抽象方法 是只有方法定义 没有 方法体的方法就是抽象 且必须用abstract修饰
abstract class Animal{
    //没有方法体的方法体就是抽象方法
    //作用 用定义子类的方法。但是抽象方法必须在子类种被实现
    abstract run(speed:number):void;
    //正常的方法  (完全方法)
    eat(food:string):void{}
}
//抽象类 和 接口的区别:  抽象类里面可以有完全方法 接口里面不能有完全方法.
interface Bird{
    fly:(speed:number)=>void;
    // walk(a:string):void{} 不能有完全方法
}
class Cat extends Animal{
    //子类 必须实现继承的抽象类里面 抽象方法.
    public run(speed:number):void{}
}
//11.3 实现接口 implements  类 可以实现接口. 从而通过接口来定义类的属性和方法结构
interface Machine2{
    price:number;
    play(m:string,n:string):void;
}
class Computer implements Machine2{//实现接口
    price: number=10;
    //类实现接口  必须实现接口里面定义的所有方法
    play(m:string,n:string):void{
        m+n;
    }
}
class Ipad implements Machine2{
    play(m: string, n: string): void {
        
    }
}
//11.4 类 和 接口都有泛型
class Phone<T>{
    name:T;
    constructor(n:T){
        this.name=n;
    }
    play(){
        let playname:T=this.name;
    }
}
let p2=new Phone(14); //自动推论
let p3=new Phone<string>('华为P50');//实例化的时候指定泛型T的类型

//接口泛型
interface Dog<T,U>{
    name:T;
    age:U
}
let d5:Dog<string,number>={
    name:'wangcai',
    age:2
}
let d6:Dog<number,string>={
    name:15,
    age:"5岁"
}